/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { BenchmarkRunner } from "../../../utils/benchmarkTsSuite";
declare function print(arg:any, arg1?:any):string;

class ValueType {
    clone() : ValueType {
        console.error("valuetype clone()");
        return this;
    }

    equals(other : ValueType) : boolean {
        return false;
    }

    set(other) : void {
        console.error("valuetype set()");
    }

    toString() : string {
        return `${''}`;
    }
}

class MathBase extends ValueType {
    public _array:Float32Array;

    constructor() {
        super();
    }

    static createFloatArray(size) : Float32Array {
        return new Float32Array(size);
    }

    get array() : Float32Array {
        return this._array;
    }
}

class Mat3 extends MathBase {
    public _array: Float32Array;
    constructor(m00: number = 1, m01: number = 0, m02: number = 0, m03: number = 0, m04: number = 1, m05: number = 0, m06: number = 0, m07: number = 0, m08: number = 1) {
        super();

        this._array = MathBase.createFloatArray(9);
        this._array[0] = m00;
        this._array[1] = m01;
        this._array[2] = m02;
        this._array[3] = m03;
        this._array[4] = m04;
        this._array[5] = m05;
        this._array[6] = m06;
        this._array[7] = m07;
        this._array[8] = m08;
    }

    static determinant(a) : number {
        const a00 = a.m00;
        const a01 = a.m01;
        const a02 = a.m02;
        const a10 = a.m03;
        const a11 = a.m04;
        const a12 = a.m05;
        const a20 = a.m06;
        const a21 = a.m07;
        const a22 = a.m08;
        return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20);
    }
}

class Mat4 extends MathBase {
    public _array: Float32Array;
    constructor(m00: number = 1, m01: number = 0, m02: number = 0, m03: number = 0, m04: number = 0, m05: number = 1, m06: number = 0, m07: number = 0, m08: number = 0, m09: number = 0, m10: number = 1, m11: number = 0, m12: number = 0, m13: number = 0, m14: number = 0, m15: number = 1) {
        super();

        this._array = MathBase.createFloatArray(16);
        this._array[0] = m00;
        this._array[1] = m01;
        this._array[2] = m02;
        this._array[3] = m03;
        this._array[4] = m04;
        this._array[5] = m05;
        this._array[6] = m06;
        this._array[7] = m07;
        this._array[8] = m08;
        this._array[9] = m09;
        this._array[10] = m10;
        this._array[11] = m11;
        this._array[12] = m12;
        this._array[13] = m13;
        this._array[14] = m14;
        this._array[15] = m15;
    }

    static clone(a) : Mat4 {
        return new Mat4(a.m00, a.m01, a.m02, a.m03, a.m04, a.m05, a.m06, a.m07, a.m08, a.m09, a.m10, a.m11, a.m12, a.m13, a.m14, a.m15);
    }

    static copy(out : Mat4, a : Mat4) : Mat4 {
        out._array[0] = a._array[0];
        out._array[1] = a._array[1];
        out._array[2] = a._array[2];
        out._array[3] = a._array[3];
        out._array[4] = a._array[4];
        out._array[5] = a._array[5];
        out._array[6] = a._array[6];
        out._array[7] = a._array[7];
        out._array[8] = a._array[8];
        out._array[9] = a._array[9];
        out._array[10] = a._array[10];
        out._array[11] = a._array[11];
        out._array[12] = a._array[12];
        out._array[13] = a._array[13];
        out._array[14] = a._array[14];
        out._array[15] = a._array[15];
        return out;
    }

    static fromQuat(out: Mat4, q: Quat) : Mat4 {
        const x = q._array[0];
        const y = q._array[1];
        const z = q._array[2];
        const w = q._array[3];
        const x2 = x + x;
        const y2 = y + y;
        const z2 = z + z;
        const xx = x * x2;
        const yx = y * x2;
        const yy = y * y2;
        const zx = z * x2;
        const zy = z * y2;
        const zz = z * z2;
        const wx = w * x2;
        const wy = w * y2;
        const wz = w * z2;
        out._array[0] = 1 - yy - zz;
        out._array[1] = yx + wz;
        out._array[2] = zx - wy;
        out._array[3] = 0;
        out._array[4] = yx - wz;
        out._array[5] = 1 - xx - zz;
        out._array[6] = zy + wx;
        out._array[7] = 0;
        out._array[8] = zx + wy;
        out._array[9] = zy - wx;
        out._array[10] = 1 - xx - yy;
        out._array[11] = 0;
        out._array[12] = 0;
        out._array[13] = 0;
        out._array[14] = 0;
        out._array[15] = 1;
        return out;
    }

    transpose() : Mat4 {
        const a01 = this._array[1];
        const a02 = this._array[2];
        const a03 = this._array[3];
        const a12 = this._array[6];
        const a13 = this._array[7];
        const a23 = this._array[11];
        this._array[1] = this._array[4];
        this._array[2] = this._array[8];
        this._array[3] = this._array[12];
        this._array[4] = a01;
        this._array[6] = this._array[9];
        this._array[7] = this._array[13];
        this._array[8] = a02;
        this._array[9] = a12;
        this._array[11] = this._array[14];
        this._array[12] = a03;
        this._array[13] = a13;
        this._array[14] = a23;
        return this;
    }

    multiply(mat : Mat4) : Mat4 {
        const a00 = this._array[0];
        const a01 = this._array[1];
        const a02 = this._array[2];
        const a03 = this._array[3];
        const a10 = this._array[4];
        const a11 = this._array[5];
        const a12 = this._array[6];
        const a13 = this._array[7];
        const a20 = this._array[8];
        const a21 = this._array[9];
        const a22 = this._array[10];
        const a23 = this._array[11];
        const a30 = this._array[12];
        const a31 = this._array[13];
        const a32 = this._array[14];
        const a33 = this._array[15];
        const v = mat._array;
        let b0 = v[0];
        let b1 = v[1];
        let b2 = v[2];
        let b3 = v[3];
        this._array[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
        this._array[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
        this._array[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
        this._array[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
        b0 = v[4];
        b1 = v[5];
        b2 = v[6];
        b3 = v[7];
        this._array[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
        this._array[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
        this._array[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
        this._array[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
        b0 = v[8];
        b1 = v[9];
        b2 = v[10];
        b3 = v[11];
        this._array[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
        this._array[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
        this._array[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
        this._array[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
        b0 = v[12];
        b1 = v[13];
        b2 = v[14];
        b3 = v[15];
        this._array[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
        this._array[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
        this._array[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
        this._array[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
        return this;
    }
}

class Vec3 extends MathBase {
    public _array: Float32Array;
    static copy(out : Vec3, a : Vec3) : Vec3 {
        out._array[0] = a._array[0];
        out._array[1] = a._array[1];
        out._array[2] = a._array[2];
        return out;
    }

    constructor(x : number = 0, y : number = 0, z : number = 0) {
        super();
        this._array = MathBase.createFloatArray(3);
        this._array[0] = x || 0;
        this._array[1] = y || 0;
        this._array[2] = z || 0;
    }

    transformMat4(matrix : Mat4) : Vec3 {
        const x = this._array[0];
        const y = this._array[1];
        const z = this._array[2];
        const v = matrix._array;
        let rhw = v[3] * x + v[7] * y + v[11] * z + v[15];
        rhw = rhw ? 1 / rhw : 1;
        this._array[0] = (v[0] * x + v[4] * y + v[8] * z + v[12]) * rhw;
        this._array[1] = (v[1] * x + v[5] * y + v[9] * z + v[13]) * rhw;
        this._array[2] = (v[2] * x + v[6] * y + v[10] * z + v[14]) * rhw;
        return this;
    }

    static transformQuat(out : Vec3, a : Vec3, q : Quat) : Vec3 {
        const ix = q._array[3] * a._array[0] + q._array[1] * a._array[2] - q._array[2] * a._array[1];
        const iy = q._array[3] * a._array[1] + q._array[2] * a._array[0] - q._array[0] * a._array[2];
        const iz = q._array[3] * a._array[2] + q._array[0] * a._array[1] - q._array[1] * a._array[0];
        const iw = -q._array[0] * a._array[0] - q._array[1] * a._array[1] - q._array[2] * a._array[2];
        out._array[0] = ix * q._array[3] + iw * -q._array[0] + iy * -q._array[2] - iz * -q._array[1];
        out._array[1] = iy * q._array[3] + iw * -q._array[1] + iz * -q._array[0] - ix * -q._array[2];
        out._array[2] = iz * q._array[3] + iw * -q._array[2] + ix * -q._array[1] - iy * -q._array[0];
        return out;
    }

    static set(out : Vec3, x: number, y: number, z: number) : Vec3 {
        out._array[0] = x;
        out._array[1] = y;
        out._array[2] = z;
        return out;
    }

    static scaleAndAdd(out : Vec3, a : Vec3, b : Vec3, scale) : Vec3 {
        out._array[0] = a._array[0] + b._array[0] * scale;
        out._array[1] = a._array[1] + b._array[1] * scale;
        out._array[2] = a._array[2] + b._array[2] * scale;
        return out;
    }

}

class Vec4 extends ValueType {
    public x : number;
    public y : number;
    public z : number;
    public w : number;

    constructor(x : number = 0, y : number = 0, z : number = 0 , w : number = 0) {
        super();
        this.x = x;
        this.y = y;
        this.z = z;
        this.w = w;
    }
    static clone(a : Vec4) : Vec4 {
        return new Vec4(a.x, a.y, a.z, a.w);
    }
}

class Quat extends MathBase {
    public _array: Float32Array;
    static copy(out : Quat, a :Quat) : Quat {
        out._array[0] = a._array[0];
        out._array[1] = a._array[1];
        out._array[2] = a._array[2];
        out._array[3] = a._array[3];
        return out;
    }
    constructor(x : number = 0, y : number = 0, z : number = 0, w : number = 1) {
        super();
        this._array = MathBase.createFloatArray(4);
        this._array[0] = x || 0;
        this._array[1] = y || 0;
        this._array[2] = z || 0;
        this._array[3] = w !== null && w !== void 0 ? w : 1;
    }

    static normalize(out : Quat, a : Quat) : Quat {
        let len = a._array[0] * a._array[0] + a._array[1] * a._array[1] + a._array[2] * a._array[2] + a._array[3] * a._array[3];

        if (len > 0) {
            len = 1 / Math.sqrt(len);
            out._array[0] = a._array[0] * len;
            out._array[1] = a._array[1] * len;
            out._array[2] = a._array[2] * len;
            out._array[3] = a._array[3] * len;
        }
        return out;
    }
}

const template_Mat3 = new Mat3();
const template_Mat4 = new Mat4(3, 4, 23, 11, 55, 33, 23, 22, 12, 54, 23, 56, 9, 73, 3, 1);
const template_Vec3 = new Vec3(4, 4, 4);
const template_Vec4 = new Vec4(3, 3, 3, 3);
const template_Quat = new Quat(3, 4, 2, 2);



function getScale(out : Vec4) : Vec4 {
    const m3_1$1 = new Mat3();
    const t = m3_1$1._array;
    const m00 = t[0];
    const m01 = t[1];
    const m02 = t[2];
    const m04 = t[3];
    const m05 = t[4];
    const m06 = t[5];
    const m08 = t[6];
    const m09 = t[7];
    const m10 = t[8];
    out.x = Math.sqrt(m00 * m00 + m01 * m01 + m02 * m02);
    out.y = Math.sqrt(m04 * m04 + m05 * m05 + m06 * m06);
    out.z = Math.sqrt(m08 * m08 + m09 * m09 + m10 * m10);

    if (Mat3.determinant(m3_1$1) < 0) {
        out.x *= -1;
    }

    return out;
}

function getWorldScale(out : Vec3) : Vec3 {
    if (out) {
        return Vec3.copy(out, template_Vec3);
    }
    return Vec3.copy(new Vec3(), template_Vec3);
}

function getRotation(out : Quat) : Quat {
    return Quat.copy(out || new Quat(), template_Quat);
}

function getWorldRotation(out : Quat) : Quat {
    return Quat.copy(out || new Quat(), template_Quat);
}

function pseudoRandom(seed : number) : number {
    seed = (seed * 9301 + 49297) % 233280;
    return seed / 233280.0;
}

function lerp(from : number, to : number, ratio : number) : number {
    return from + (to - from) * ratio;
}

function repeat(t : number, length : number) : number {
    return t - Math.floor(t / length) * length;
}

function pingPong(t : number, length : number) : number {
    t = repeat(t, length * 2);
    t = length - Math.abs(t - length);
    return t;
}

function wrapRepeat(time : number, prevTime : number, nextTime : number) : number {
    return prevTime + repeat(time - prevTime, nextTime - prevTime);
}

function wrapPingPong(time : number, prevTime : number, nextTime : number) : number {
    return  prevTime + pingPong(time - prevTime, nextTime - prevTime);
}

function binarySearchEpsilon(array : number[], value : number, EPSILON : number = 1e-6) : number {
    let low : number = 0;
    let high : number = array.length - 1;
    let middle : number = high >>> 1;

    for (; low <= high; middle = low + high >>> 1) {
        const test = array[middle];

        if (test > value + EPSILON) {
            high = middle - 1;
        } else if (test < value + EPSILON) {
            low = middle + 1;
        } else {
            return middle;
        }
    }

    return ~low;
}

function bezizerInterprolate(p0 : number, p1 : number, p2 : number, p3 : number, t : number) : number {
    const u = 1 - t;
    const coeff0 = u * u * u;
    const coeff1 = 3 * u * u * t;
    const coeff2 = 3 * u * t * t;
    const coeff3 = t * t * t;
    return coeff0 * p0 + coeff1 * p1 + coeff2 * p2 + coeff3 * p3;
}

const EQN_EPS = 1e-9;
function isZero(x : number) : boolean {
    return x > -EQN_EPS && x < EQN_EPS;
}

function solveCubic(coeff0 : number, coeff1 : number, coeff2 : number, coeff3 : number, solutions : number[]) : number {
    const a = coeff2 / coeff3;
    const b = coeff1 / coeff3;
    const c = coeff0 / coeff3;
    const sqrA = a * a;
    const p = 1.0 / 3.0 * (-1.0 / 3 * sqrA + b);
    const q = 1.0 / 2.0 * (2.0 / 27.0 * a * sqrA - 1.0 / 3 * a * b + c);
    const cubicP = p * p * p;
    const d = q * q + cubicP;
    let nSolutions = 0;

    if (isZero(d)) {
        if (isZero(q)) {
            solutions[0] = 0;
            return 1;
        } else {
            const u = Math.cbrt(-q);
            solutions[0] = 2 * u;
            solutions[1] = -u;
            return 2;
        }
    } else if (d < 0) {
        const phi = 1.0 / 3 * Math.acos(-q / Math.sqrt(-cubicP));
        const t = 2 * Math.sqrt(-p);
        solutions[0] = t * Math.cos(phi);
        solutions[1] = -t * Math.cos(phi + Math.PI / 3);
        solutions[2] = -t * Math.cos(phi - Math.PI / 3);
        nSolutions = 3;
    } else {
        const sqrtD = Math.sqrt(d);
        const u = Math.cbrt(sqrtD - q);
        const v = -Math.cbrt(sqrtD + q);
        solutions[0] = u + v;
        nSolutions = 1;
    }

    const sub = 1.0 / 3 * a;

    for (let i = 0; i < nSolutions; ++i) {
        solutions[i] -= sub;
    }

    return nSolutions
}

function getParamFromCubicSolution(solutions : number[], solutionsCount : number, x : number) : number {
    let param = x;

    if (solutionsCount === 1) {
        param = solutions[0];
    } else {
        param = -Infinity;

        for (let iSolution = 0; iSolution < solutionsCount; ++iSolution) {
            const solution = solutions[iSolution];

            if (solution >= 0.0 && solution <= 1.0) {
                if (solution > param) {
                    param = solution;
                }
            }
        }

        if (param === -Infinity) {
            param = 0.0;
        }
    }

    return param;
}


function evalBetweenTwoKeyFrames(prevTime : number = 15.3, prevValue : number = 33.4, nextTime : number = 21.5, nextValue : number= 45.9, ratio : number = 0.4) : number {
    const dt = nextTime - prevTime;
    const ONE_THIRD = 1.0 / 3.0;
    const prevTangent = 2;
    const nextTangent = 3;
    const p1 = prevValue + ONE_THIRD * prevTangent * dt;
    const p2 = nextValue - ONE_THIRD * nextTangent * dt;
    bezizerInterprolate(prevValue, p1, p2, nextValue, ratio);
    let x = dt;
    let y = dt * prevTangent;
    const prevTangentWeight = Math.sqrt(x * x + y * y) * ONE_THIRD;
    const angle0 = Math.atan(prevTangent);
    const tx0 = Math.cos(angle0) * prevTangentWeight + prevTime;
    const ty0 = Math.sin(angle0) * prevTangentWeight + prevValue;
    x = dt;
    y = dt * nextTangent;
    const nextTangentWeight = Math.sqrt(x * x + y * y) * ONE_THIRD;
    const angle1 = Math.atan(nextTangent);
    const tx1 = Math.cos(angle1) * nextTangentWeight + nextTime;
    const ty1 = -Math.sin(angle1) * nextTangentWeight + nextValue;
    const dx = dt;
    const u0x = (tx0 - prevTime) / dx;
    const u1x = (tx1 - prevTime) / dx;
    const u0y = ty0;
    const u1y = ty1;
    const coeff0 = 0.0;
    const coeff1 = 3.0 * u0x;
    const coeff2 = 3.0 * u1x - 6.0 * u0x;
    const coeff3 = 3.0 * (u0x - u1x) + 1.0;
    const solutions : number[] = [0.0, 0.0, 0.0];
    const nSolutions = solveCubic(coeff0 - ratio, coeff1, coeff2, coeff3, solutions);
    const param = getParamFromCubicSolution(solutions, nSolutions, ratio);
    y = bezizerInterprolate(prevValue, u0y, u1y, nextValue, param);
    return y;
}


function evaluate(time : number = 55) : number {
    var firstTime = 10;
    var lastTime = 20;
    time = wrapRepeat(time, firstTime, lastTime);
    time = wrapRepeat(time, firstTime, lastTime);
    time = 15;
    time = wrapPingPong(time, firstTime, lastTime);
    time = wrapPingPong(time, firstTime, lastTime);
    let array : number[] = [1.1, 2.3, 4.3, 4.9, 9.3, 10.3, 34, 45];
    var value = 4;
    binarySearchEpsilon(array, 4);
    return evalBetweenTwoKeyFrames();
}

function evaluate1(time, rndRatio) : number {
    return lerp(evaluate(time), evaluate(time), rndRatio) * 1;
}

class LifeTime {
    remainingLifetime : number;
    startLifetime : number;
}

const FORCE_OVERTIME_RAND_OFFSET = 212165;
function animate(p : LifeTime, dt : number = 2) : void {
    const normalizedTime = 1 - p.remainingLifetime / p.startLifetime;
    let _temp_v3 = new Vec3();
    const force = Vec3.set(_temp_v3, evaluate1(normalizedTime, pseudoRandom(FORCE_OVERTIME_RAND_OFFSET)), evaluate1(normalizedTime, pseudoRandom(FORCE_OVERTIME_RAND_OFFSET)), evaluate1(normalizedTime, pseudoRandom(FORCE_OVERTIME_RAND_OFFSET)));

    var rotation = new Quat();
    Vec3.transformQuat(force, force, rotation);

    let velocity = new Vec3();
    Vec3.scaleAndAdd(velocity, velocity, force, dt);
    let ultimateVelocity = new Vec3();
    Vec3.copy(ultimateVelocity, velocity);
}

class Attrs {
    constructor(a : number, b : number,c : number) {
        this.x = a;
        this.y = b;
        this.z = c;
    }
    x : number;
    y : number;
    z : number;
}

function addParticleVertexData(index : number, pvdata : Attrs[]) : void {
    var _vdataF32 : Float32Array = new Float32Array(20);
    var _vertCount = 20;
    for (let i = 0; i < _vertCount; i++) {
        _vdataF32[0] = pvdata[0].x;
        _vdataF32[1] = pvdata[0].y;
        _vdataF32[2] = pvdata[0].z;
        _vdataF32[5] = pvdata[1].z;
        _vdataF32[6] = pvdata[2].x;
        _vdataF32[7] = pvdata[2].y;
        _vdataF32[8] = pvdata[2].z;
        _vdataF32[9] = pvdata[3].x;
        _vdataF32[10] = pvdata[3].y;
        _vdataF32[11] = pvdata[3].z;
    }
}

function _fillStrecthedData(idx : number) : void {
    for (let j = 0; j < 4; ++j) {
        var _attrs : Attrs[] = [new Attrs(1, 1, 1),
            new Attrs(2, 2, 2),
            new Attrs(3, 3, 3),
            new Attrs(4, 4, 4),
            new Attrs(5, 5, 5),];

        addParticleVertexData(idx++, _attrs);
    }
}

class ParticleSystem {
    public _tempWorldTrans : Mat4 = new Mat4(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
    public _tempScale : Vec4 = new Vec4();
    public _tempWorldScale :Vec3 = new Vec3();
    public _tempRotation : Quat = new Quat();
    public _tempWorldRotation : Quat = new Quat();
    public _updateList : Map<string, number> = new Map();
    public _gravity : Vec3 = new Vec3(0, -10, 0);
    public randomSeed : number = 0;
    public _fillDataFunc = _fillStrecthedData;

    constructor() {
        this._updateList.set("key1", 1);
        this._updateList.set("key2", 2);
        this._updateList.set("key3", 3);
        this._updateList.set("key4", 4);
        this._updateList.set("key5", 5);
        this._updateList.set("key6", 6);
    }

    updateRenderData() {
        let idx = 0;

        for (let i = 0; i < 100; ++i) {
            idx = i * 4;

            this._fillDataFunc(idx);
        }
    }

    updateParticles(dt : number = 5) : number {
        Mat4.copy(this._tempWorldTrans, template_Mat4);

        getScale(this._tempScale);
        getWorldScale(this._tempWorldScale);

        getRotation(this._tempRotation);
        getWorldRotation(this._tempWorldRotation);

        Mat4.fromQuat(this._tempWorldTrans, this._tempRotation);
        this._tempWorldTrans.transpose();

        for (var i = 0; i < 20; i++) {
            const time = i * 10;
            evaluate(time);
            evaluate(time);
            lerp(i * 10 + 1.3, i * 13.4 + 3.4, pseudoRandom(this.randomSeed));
            Vec3.copy(this._tempWorldScale, template_Vec3);

            for (var j = 0; j < 15; j++) {
                let p : LifeTime = new LifeTime();
                p.remainingLifetime = i + 13.6;
                p.startLifetime = i + 20.3;
                animate(p, dt);
            }
            
            var position1 = new Vec3();
            var position2 = new Vec3();
            var position3 = new Vec3();
            Vec3.scaleAndAdd(position1, position2, position3, dt);
            let tempP : LifeTime = new LifeTime();
            tempP.remainingLifetime = 40.7;
            tempP.startLifetime = 54.2;
            animate(tempP, dt);
        }

        this._gravity.transformMat4(this._tempWorldTrans);

        return 14;
    }

    animte() {

        Quat.normalize(template_Quat, template_Quat);

        template_Mat4.multiply(template_Mat4);
    }

    frameMove() {

        this.fillPassed();
    }

    fillPassed() {
        const buffer : ArrayBuffer = new ArrayBuffer(16);
        const view : DataView = new DataView(buffer);
        for (let i = 0; i < 10; i++) {
            const max = BigInt(2n ** 64n - 1n);
            view.setBigUint64(i, max);
            print(view.getBigUint64(i).toString());
        }
    }

}

export function RunCocosAirPlane(){
    let system : ParticleSystem = new ParticleSystem();
    let start: number = new Date().getTime();
    for (var i = 0; i < 300; i++) {
        system.updateParticles();
        system.updateRenderData();
        system.animte();
    }
    let end: number = new Date().getTime();
    // print("cocos_airplan_total :", end - start);
    // print("execute successfully");
    return (end - start);
}

let runner1 = new BenchmarkRunner("Cocos - RunCocosAirPlane", RunCocosAirPlane);
runner1.run();
